<!--
 * @Author: yao
 * @Date: 2024-11-21 08:31:44
 * @LastEditTime: 2025-02-18 15:33:33
 * @LastEditors: yao
 * @Description: 
 * @FilePath: \jdev-web-el\src\components\Dock\index.vue
-->
<template>
  <section class="fav_menu">
    <nav class="nav-bar">
      <ul class="nav-list" name="zoom-in-center" tag="ul">
        <li class="nav-item" v-for="(menu, index) in favLeftMenu" :key="index" @click="toMenu(menu)" :id="index">
          <div href="#" class="nav-item__link"><img v-if="menu.img" :src="menu.img" loading="eager"
              alt="Notion app icon" class="image">
            <div class="image_text" v-else :style="getTextStyle(menu.meta.title)"><span>{{ menu.meta.title.substring(0,
              4)
                }}</span>
            </div>
          </div>
          <div v-show="menu.meta.title" class="nav-item__tooltip">
            <div>{{ menu.meta.title }}</div>
          </div>
        </li>

        <li class="nav-item" :id="favLeftMenu ? favLeftMenu.length : 0">
          <el-dropdown placement="top" trigger="hover" :hide-on-click="false" @visible-change="showMenus">
            <div class="nav-item__link"><img
                src="https://cdn.prod.website-files.com/6728a3e6f4f4161c235bc519/6728a6bea73fcc6ee568f6f0_webflow.png"
                loading="eager" alt="Webflow app icon" class="image"></div>
            <template #dropdown>
              <div id="menuContent" style="width: 580px;height: 600px;display: flex;
    flex-direction: column;padding:16px;background: rgba(255, 255, 255, 0.7);backdrop-filter: blur(10px);">
                <JSearch v-model="inputValue" style="margin-bottom: 10px;"></JSearch>
                <FlatMenu style="flex-grow: 1;width: 100%;overflow: auto;" @favEvent="favEvent" :menus="menuList">
                </FlatMenu>
              </div>
            </template>
          </el-dropdown>
          <div class="nav-item__tooltip">
            <div>菜单</div>
          </div>
        </li>


        <li class="nav-item" v-for="(menu, index) in favRightMenu" :key="favLeftMenu.length + index + 1"
          @click="toMenu(menu)" :id="favLeftMenu.length + index + 1">
          <div href="#" class="nav-item__link"><img v-if="menu.img" :src="menu.img" loading="eager"
              alt="Notion app icon" class="image">
            <div class="image_text" v-else :style="getTextStyle(menu.meta.title)"><span>{{ menu.meta.title.substring(0,
              4)
                }}</span>
            </div>
          </div>
          <div v-show="menu.meta.title" class="nav-item__tooltip">
            <div>{{ menu.meta.title }}</div>
          </div>
        </li>
      </ul>
    </nav>
  </section>
</template>

<script setup lang='ts'>
import { ref, onMounted, computed, nextTick } from 'vue'
import { useRouter } from 'vue-router';
import FlatMenu from './FlatMenu.vue';
import { useUserStore } from '@/stores/modules/user';
import { debounce } from 'lodash';
import JSearch from '@/components/JSearch/index.vue';
const router = useRouter();
const useUser = useUserStore()
const inputValue = ref('')
const isMenu = ref(false)
const currentMenu = ref(-2)
onMounted(() => {
  init()
})
const init = () => {
  const navItems = document.querySelectorAll('.nav-item');
  const menu = document.getElementById('menuContent')
  menu?.removeEventListener('mouseenter', menuEnter)
  menu?.removeEventListener('mouseleave', menuLeave)
  menu?.addEventListener('mouseenter', menuEnter)
  menu?.addEventListener('mouseleave', menuLeave);
  navItems.forEach((item, index) => {
    item.removeEventListener('mouseenter', itemEnter);
    item.removeEventListener('mouseleave', itemLeave);
  });
  navItems.forEach((item, index) => {
    item.addEventListener('mouseenter', itemEnter);
    item.addEventListener('mouseleave', itemLeave);
  });
}
const menuLeave = (val) => {
  const navItems = document.querySelectorAll('.nav-item');
  currentMenu.value = useUser.favMenu.length ? Math.floor(useUser.favMenu.length / 2) : 0
  navItems[currentMenu.value].classList.remove('hover');
  toggleSiblingClass(navItems, currentMenu.value, -1, 'sibling-close', false); // Previous sibling
  toggleSiblingClass(navItems, currentMenu.value, 1, 'sibling-close', false);  // Next sibling
  toggleSiblingClass(navItems, currentMenu.value, -2, 'sibling-far', false);   // Previous-previous sibling
  toggleSiblingClass(navItems, currentMenu.value, 2, 'sibling-far', false);    // Next-next sibling
}
const menuEnter = (val) => {
  const navItems = document.querySelectorAll('.nav-item');
  currentMenu.value = useUser.favMenu.length ? Math.floor(useUser.favMenu.length / 2) : 0
  navItems[currentMenu.value].classList.add('hover');
  toggleSiblingClass(navItems, currentMenu.value, -1, 'sibling-close', true); // Previous sibling
  toggleSiblingClass(navItems, currentMenu.value, 1, 'sibling-close', true);  // Next sibling
  toggleSiblingClass(navItems, currentMenu.value, -2, 'sibling-far', true);   // Previous-previous sibling
  toggleSiblingClass(navItems, currentMenu.value, 2, 'sibling-far', true);    // Next-next sibling
}
const itemLeave = (val) => {
  const navItems = document.querySelectorAll('.nav-item');
  currentMenu.value = Number(val.target.id)
  val.target.classList.remove('hover');
  toggleSiblingClass(navItems, val.target.id, -1, 'sibling-close', false); // Previous sibling
  toggleSiblingClass(navItems, val.target.id, 1, 'sibling-close', false);  // Next sibling
  toggleSiblingClass(navItems, val.target.id, -2, 'sibling-far', false);   // Previous-previous sibling
  toggleSiblingClass(navItems, val.target.id, 2, 'sibling-far', false);    // Next-next sibling
  currentMenu.value = -2
}
const itemEnter = (val) => {
  currentMenu.value = Number(val.target.id)
  val.target.classList.add('hover');
  const navItems = document.querySelectorAll('.nav-item');
  toggleSiblingClass(navItems, val.target.id, -1, 'sibling-close', true); // Previous sibling
  toggleSiblingClass(navItems, val.target.id, 1, 'sibling-close', true);  // Next sibling
  toggleSiblingClass(navItems, val.target.id, -2, 'sibling-far', true);   // Previous-previous sibling
  toggleSiblingClass(navItems, val.target.id, 2, 'sibling-far', true);    // Next-next sibling
}
const toggleSiblingClass = (items, index, offset, className, add) => {
  const sibling = items[Number(index) + offset];
  if (sibling) {
    sibling.classList.toggle(className, add);
  }
};
const toMenu = (val) => {
  router.replace(`${val.path || ''}`);
}
const showMenus = (val) => {
  isMenu.value = val
}
const favLeftMenu = computed(() => {
  const middleIndex = useUser.favMenu.length ? Math.floor(useUser.favMenu.length / 2) : 0;
  return useUser.favMenu.slice(0, middleIndex)
})
const favRightMenu = computed(() => {
  const middleIndex = useUser.favMenu.length ? Math.floor(useUser.favMenu.length / 2) : 0;
  return useUser.favMenu.slice(middleIndex)
})
const menuList = computed(() => {
  return filterByNameContains(processMenuList(flattenTree(useUser.menus), useUser.favMenu), inputValue.value)
})

const processMenuList = (menuList, favList) => {
  return menuList.map(item => {
    // 创建一个新的对象以避免直接修改原始对象
    const newItem = { ...item };

    // 判断当前项是否在收藏列表中
    if (isFavorite(newItem, favList)) {
      newItem.fav = true;
    }

    return newItem;
  });
}
const filterByNameContains = (menuItems: any, searchString: string) => {
  if (!searchString.trim()) {
    return menuItems
  }
  const findChildren = (items, parentId) => items
    .filter(item => item.parentId === parentId)
    .flatMap(child =>
      // 匹配成功或递归调用findChildren获取更深层级的孩子节点
      (child.name.includes(searchString) || child.isLeaf === false) ?
        [child, ...findChildren(items, child.id)] :
        []
    );

  return menuItems
    .filter(menuItem => menuItem.name.includes(searchString)) // 初步筛选出匹配名字的项
    .flatMap(matchedItem =>
      matchedItem.isLeaf ?
        [matchedItem] :
        [matchedItem, ...findChildren(menuItems, matchedItem.id)]
    );
}
const isFavorite = (item, favList) => {
  return favList.some(favItem => favItem.id === item.id && (item.name));
}
const generateColor = (text: string): { bgColor: string, textColor: string } => {
  const hashString = (str) => {
    let hash = 0;
    for (let i = 0; i < str.length; i++) {
      hash += str.charCodeAt(i);
    }
    return hash;
  };

  // 根据哈希值生成柔和的颜色
  const hashToSoftColor = (hash) => {
    // 使用哈希值来生成RGB颜色
    const r = (hash & 0xFF0000) >> 16;
    const g = (hash & 0x00FF00) >> 8;
    const b = hash & 0x0000FF;

    // 调节颜色使其更柔和且护眼
    const adjustForEyes = (value) => {
      // 目标是让RGB值接近于舒适的范围
      const targetValue = 175; // 中等亮度的参考值
      const diff = value - targetValue;
      // 减少差异，使颜色更加柔和
      return Math.round(targetValue + diff * 0.5);
    };

    const adjustedR = adjustForEyes(r);
    const adjustedG = adjustForEyes(g);
    const adjustedB = adjustForEyes(b);

    // 返回格式化的十六进制颜色代码
    return `#${((1 << 24) + (adjustedR << 16) + (adjustedG << 8) + adjustedB).toString(16).slice(1).toUpperCase()}`;
  };
  const textHash = hashString(text);
  return { bgColor: "#fff", textColor: hashToSoftColor(textHash) };
}

const getTextStyle = computed(() => {
  return (name: string) => {
    const style = generateColor(name)
    return {
      'background': style.bgColor,
      'color': style.textColor
    }
  }
});

const favEvent = debounce((isFav: boolean, menu: any) => {
  if (isFav) {
    useUser.addFav(menu)
  } else {
    useUser.removeFav(menu.id)
  }
  const navItems = document.querySelectorAll('.nav-item');
  for (const item of navItems) {
    item.classList.remove('hover');
    item.classList.remove('sibling-close');
    item.classList.remove('sibling-far');
  }
  nextTick(() => {
    currentMenu.value = useUser.favMenu.length ? Math.floor(useUser.favMenu.length / 2) : 0
    const navItems = document.querySelectorAll('.nav-item');
    init()
    navItems[currentMenu.value].classList.add('hover');
    toggleSiblingClass(navItems, currentMenu.value, -1, 'sibling-close', true); // Previous sibling
    toggleSiblingClass(navItems, currentMenu.value, 1, 'sibling-close', true);  // Next sibling
    toggleSiblingClass(navItems, currentMenu.value, -2, 'sibling-far', true);   // Previous-previous sibling
    toggleSiblingClass(navItems, currentMenu.value, 2, 'sibling-far', true);    // Next-next sibling


  })
})



const flattenTree = (data, parentId = null, level = 0) => {
  return data.reduce((acc, current) => {
    // 判断是否是叶子节点
    const isLeaf = !current.children || current.children.length === 0;

    const newItem = {
      ...current,
      parentId: parentId, // 添加 parentId
      level: level, // 添加 level 属性
      isLeaf: isLeaf // 添加 isLeaf 属性
    };
    // 删除原始的 children 属性，因为我们已经处理了它们
    delete newItem.children;
    acc.push(newItem);

    // 如果存在子节点，则递归处理，并增加层级
    if (!isLeaf) {
      acc.push(...flattenTree(current.children, current.id, level + 1));
    }
    return acc;
  }, []);
}
</script>
<style scoped lang='scss'>
.ep-dropdown__popper.ep-popper {
  border-radius: 12px;
  background: transparent;
}

.fav_menu {


  font-family: Arial,
    sans-serif;
  z-index: 100;
  pointer-events: none;
  justify-content: center;
  align-items: flex-end;
  display: flex;
  position: fixed;
  bottom: var(--ep-dock-bottom);
  left: 0;
  right: 0;
  margin-left: auto;
  margin-right: auto;
  width: 100vw;

  .nav-list {
    flex-flow: row;
    justify-content: center;
    align-items: flex-end;
    margin-bottom: 0;
    padding: 0 0.6rem;
    display: flex;
    scroll-snap-type: x mandatory;
    scrollbar-width: none;
    background: rgba(255, 255, 255, 0.3);
    backdrop-filter: blur(15px);
    border-radius: 22px;
    box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
    border-radius: 22px;
    overflow-y: visible;
<<<<<<< HEAD
    height: 3.7rem;
=======
    height: 4.2rem;
>>>>>>> 1b6dd3c15f0f0fca2b3ab51833658be417980567
    transition: all 0.3s ease;
  }

  .nav-list::-webkit-scrollbar {
    display: none;
  }

  .nav-item {
    justify-content: center;
    align-items: center;
<<<<<<< HEAD
    width: 3.3rem;
=======
    width: 3.7rem;
>>>>>>> 1b6dd3c15f0f0fca2b3ab51833658be417980567
    transition: width .5s cubic-bezier(.16, 1, .3, 1);
    display: flex;
    position: relative;
    box-sizing: border-box;
<<<<<<< HEAD
    margin: 0.5rem 0;
    font-size: 0.8rem;
=======
    margin: 0.6rem 0;
    font-size: 1.0rem;
>>>>>>> 1b6dd3c15f0f0fca2b3ab51833658be417980567
    cursor: pointer;
  }

  .nav-item.hover {
    width: 5.5rem;

    &>div>div>span {
      scale: 1.5;
    }
  }

  .nav-item.sibling-close {
    width: 4.5rem;

    &>div>div>span {
      scale: 1.3;
    }
  }

  .nav-item.sibling-far {
    width: 4rem;

    // font-size: 1.3rem;
    &>div>div>span {
      scale: 1.1;
    }
  }

  .nav-item__link {
    z-index: 1;
    pointer-events: auto;
    justify-content: center;
    align-items: center;
    width: 100%;
    height: 100%;
    padding-left: .3rem;
    padding-right: .3rem;
    display: flex;
    position: relative;
    box-sizing: border-box;
  }

  .image {
    object-fit: contain;
    width: 100%;
    box-sizing: border-box;
    border-radius: 12px;
  }

  .image_text {
    aspect-ratio: 1 / 1;
    width: 100%;
    padding: 3px;
    box-sizing: border-box;
    border-radius: 12px;
    display: flex;
    justify-content: center;
    align-items: center;
    font-weight: 400;
    text-align: center;
    overflow: hidden;
    line-height: 1.4;

    span {
      display: inline-block;
      width: 2.5rem;
      white-space: pre-wrap;
      word-break: break-all;
      transition: all .5s cubic-bezier(.16, 1, .3, 1);
    }
  }

  .nav-item__tooltip {
    z-index: 0;
    background-color: #fff;
    opacity: 0;
    white-space: nowrap;
    border-radius: 12px;
    padding: 12px;
    font-size: 1.4rem;
    text-align: center;
    min-width: 8rem;
    box-sizing: border-box;
    transition: transform .5s cubic-bezier(.16, 1, .3, 1), opacity .5s cubic-bezier(.16, 1, .3, 1);
    position: absolute;
    top: 0;
    transform: translate(0, -80%);
    font-weight: 400;
  }

  .nav-item:hover .nav-item__tooltip {
    opacity: 1;
    transform: translate(0px, -140%);
  }


}
</style>
